(*
This file is part of the Lustre reader

* Copyright (c) 2010, Nicola Camuffo.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Nicola Camuffo, nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*)


open Lustypes
open Utils


(* tables and functions in order to resolve this problem: in Lustre code i provide an entity (e.g. constant)
   first of its definition in package or model body. i identify provided entities by their ids, but
   they normally are created and used during creations (definitions) of entities.
   the following tables stores temporarily entities with their info (e.g. type) in order to
   obtain them at the moment of definition and thus really create entities.
*)

(* type id -> value *)
let providedtypehash = (Hashtbl.create 10 : (_id,_type)Hashtbl.t)

(* constant id -> type, value *)
let providedconsthash = (Hashtbl.create 10 : (_id,(_type * _expression))Hashtbl.t)

(* node id -> input vars, output vars *)
let providednodehash = (Hashtbl.create 10 : (_id,(_id list * _id list))Hashtbl.t)

(* function id -> input vars, output vars *)
let providedfunchash = (Hashtbl.create 10 : (_id,(_id list * _id list))Hashtbl.t)

(* entity name -> id: it is used during definitions, when i get the entity name *)
let providedidhash = (Hashtbl.create 10 : (_sym,_id)Hashtbl.t)


let provide_type id name value =
  Hashtbl.replace providedidhash name id;
  Hashtbl.replace providedtypehash id value

let provide_const id name typ value =
  Hashtbl.replace providedidhash name id;
  Hashtbl.replace providedconsthash id (typ,value)

let provide_node id name ins outs =
  Hashtbl.replace providedidhash name id;
  Hashtbl.replace providednodehash id (ins,outs)

let provide_func id name ins outs =
  Hashtbl.replace providedidhash name id;
  Hashtbl.replace providedfunchash id (ins,outs)


let provided_id = Hashtbl.find providedidhash

let provided_type_info = Hashtbl.find providedtypehash

let provided_const_info = Hashtbl.find providedconsthash

let provided_node_info = Hashtbl.find providednodehash

let provided_func_info = Hashtbl.find providedfunchash


(* tables that stores all entities that can raise a doubt about their definition and
	 provide information (e.g. a constant can have different value under body statement and
	 'provide' statement) *)
	 
(* DOUBTFUL ENTITIES *)

(* model id -> entity id list *)
let doubtshash = (Hashtbl.create 10 : (_id,_id list)Hashtbl.t)

	
let get_doubtful mid =
	let s = (string_of_int mid) ^ " -> doubtful entities not found" in
	safe_find doubtshash mid s
	
let add_doubtful mid id =
  let s = (string_of_int id) ^ " -> already marked as doubt by " ^ (string_of_int mid) in
	safe_set_in_list doubtshash mid id s


(* CAUSES *)
	
type _doubt_cause =
	TYPE_VALUE_MISMATCH
	| CONST_TYPE_MISMATCH
	| CONST_VALUE_MISMATCH
	| NODE_NUMBER_OF_VARS_MISMATCH
	| NODE_TYPE_OF_VARS_MISMATCH

(* entity id -> doubt cause *)
let causehash = (Hashtbl.create 10 : (_id,_doubt_cause)Hashtbl.t)


let get_cause id =
	let s = (string_of_int id) ^ " -> doubt cause not found" in
	safe_find causehash id s

let add_cause id cause =
  let s = (string_of_int id) ^ "-> altready stored with its cause" in
	safe_set causehash id cause s
	